package com.soft.base.mybatis.util;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.soft.base.enums.SortEnum;
import com.soft.base.protocol.ResultT;
import com.xiaoleilu.hutool.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * class
 *
 * @author user
 * @date 2020/06/05
 */
@Slf4j
public class SortUtil {
    public static ResultT sort(List<?> all, Long pid, Long id, SortEnum sortEnum, BaseMapper mapper) {
        List<?> sortList = all.stream().filter(o -> Objects.equals(BeanUtil.getFieldValue(o, "pid"), pid)).collect(Collectors.toList());
        boolean success = false;
        try {
            Integer existsIndex = null;
            for (Integer i = 0; i < sortList.size(); i++) {
                if (Objects.equals(getId(sortList.get(i)), id)) {
                    existsIndex = i;
                    break;
                }
            }
            if (existsIndex == null) {
                return ResultT.error("排序失败");
            }
            Integer old = (Integer) BeanUtil.getFieldValue(sortList.get(existsIndex), "sort");
            switch (sortEnum) {
                case UP:
                    if (existsIndex > 0) {
                        setSort(sortList.get(existsIndex), getSort(sortList.get(existsIndex - 1)));
                        mapper.updateById(sortList.get(existsIndex));
                        setSort(sortList.get(existsIndex - 1), old);
                        mapper.updateById(sortList.get(existsIndex - 1));
                        success = true;
                    } else {
                        return ResultT.error("已经是最顶部");
                    }
                    break;
                case DOWN:
                    if (existsIndex < sortList.size() - 1) {
                        setSort(sortList.get(existsIndex), getSort(sortList.get(existsIndex + 1)));
                        mapper.updateById(sortList.get(existsIndex));
                        setSort(sortList.get(existsIndex + 1), old);
                        mapper.updateById(sortList.get(existsIndex + 1));
                        success = true;
                    } else {
                        return ResultT.error("已经是最底部");
                    }
                    break;
                case TOP:
                    if (existsIndex > 0) {
                        Integer number = 2;
                        for (Integer i = 0; i < sortList.size(); i++) {
                            if (i.equals(existsIndex)) {
                                setSort(sortList.get(i), 1);
                            } else {
                                setSort(sortList.get(i), number++);
                            }
                            mapper.updateById(sortList.get(i));
                        }
                        success = true;
                    }
                    break;
                case BOTTOM:
                    if (existsIndex < sortList.size() - 1) {
                        Integer number = 1;
                        for (Integer i = 0; i < sortList.size(); i++) {
                            if (i.equals(existsIndex)) {
                                continue;
                            } else {
                                setSort(sortList.get(i), number++);
                            }
                            mapper.updateById(sortList.get(i));
                        }
                        setSort(sortList.get(existsIndex), number++);
                        mapper.updateById(sortList.get(existsIndex));
                        success = true;
                    }
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("SortUtil.sort.error", e);
        }
        if (success) {
            return ResultT.success();
        }
        return ResultT.error("排序失败");
    }

    private static void setSort(Object bean, Integer value) throws Exception {
        bean.getClass().getDeclaredMethod("setSort", Integer.class).invoke(bean, value);
    }

    private static Integer getSort(Object bean) {
        return ((Integer) BeanUtil.getFieldValue(bean, "sort"));
    }

    private static Long getId(Object bean) throws Exception {
        try {
            return (Long) bean.getClass().getDeclaredMethod("getId").invoke(bean);
        } catch (Exception e) {
            try {
                return (Long) bean.getClass().getSuperclass().getDeclaredMethod("getId").invoke(bean);
            } catch (Exception e1) {

            }
        }
        return 0L;
    }
}
